/**************************************************************
 * 
 * Copyright ? 2009，北京福富软件技术股份有限公司
 * All Rights Reserved.
 * ------------------------------------------------------------
 * 文件名称：ExcelWriter.java
 * 文件摘要：[Excel写入]web层处理
 * 初始版本：V2.0.0
 * 初始作者：ChenKQ
 * 完成日期：2013-03-07
 * 
 **************************************************************/
package com.util;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

/**************************************************************************
 * 
 * 类名：ExcelWriter<br>
 * <br>
 * 功能：Excel写入程序<br>
 * <br>
 * 作者：ChenKQ 2013-03-07<br>
 * <br>
 * 属性列表：<br>
 * private WritableWorkbook workBook<br>
 * ...<br>
 * <br>
 * 方法列表：<br>
 * public void write(List data, ExcelInfo excelInfo) <br>
 * ...<br>
 * <br>
 * 修改记录：<br>
 * 日期 修改人 修改说明<br>
 * 
 **************************************************************************/
public class ExcelMultiWriter {

	/**
	 * Excel的信息类封装
	 * 
	 * @author 郑炎
	 * 
	 */
	public static class ExcelInfo {
		/**
		 * 页名(第n页可以用 "第%i页" 表示)
		 */
		public String SheetName;
		/**
		 * 表头
		 */
		public String[] Headers;

		/**
		 * 对象的属性列表
		 */
		public String[] Propertys;

		/**
		 * 内容的格式化串(例如 Bean的某个属性的值为
		 * “20”，要输出“20个域名”，可以写作“%v个域名”,如果是要导出图片的话：{image})
		 */
		public String[] ContentFormat;

		public ExcelInfo() {
		}
	}

	private HSSFWorkbook workBook;

	private FileOutputStream fileOut;

	/**
	 * 导出进度
	 */
	private float progress;

	/**
	 * 获取导出进度
	 * 
	 * @return 导出进度
	 */
	public float getProgress() {
		return progress;
	}

	/**
	 * 图片宽度
	 */
	private int imageWidth = 1;

	/**
	 * 图片高度
	 */
	private int imageHeight = 1;

	/**
	 * 构造方法
	 * 
	 * @param filePath
	 *            文件路径
	 * @throws IOException
	 */
	public ExcelMultiWriter(String filePath) throws IOException {
		workBook = new HSSFWorkbook();// 建立新HSSFWorkbook对象
		fileOut = new FileOutputStream(filePath);

	}

	/**************************************************************
	 * 
	 * 函数名：write<br>
	 * <br>
	 * 功能：导出Excel<br>
	 * <br>
	 * 作者：ZhengYan 2013-10-14<br>
	 * <br>
	 * @param datas 导出的数据
	 * @param excelInfo Excel的信息类封装数组
	 * @throws RowsExceededException
	 * @throws WriteException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws IOException
	 * @throws NoSuchFieldException
	 * <br>
	 * 修改记录：<br>
	 * 		日期				修改人			修改说明<br>
	 * 
	 **************************************************************/
	public HSSFWorkbook write(List[] datas, ExcelInfo[] excelInfos)
			throws RowsExceededException, WriteException, SecurityException,
			NoSuchMethodException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException, IOException, NoSuchFieldException {

		for (int k = 0; k < datas.length; k++) {
			List data = datas[k];
			ExcelInfo excelInfo = excelInfos[k];
			int rowAllCount = data.size();

			int rowCurrent = 0;
			int pageCount = rowAllCount % 65535 == 0 ? rowAllCount / 65535
					: rowAllCount / 65535 + 1;

			if (rowAllCount > 0) {
				for (int i = 0; i < pageCount; i++) {
					HSSFSheet sheet = workBook.createSheet(excelInfo.SheetName
							.replace("%i", String.valueOf((k + 1 ) * (i + 1))));

					HSSFRow row = sheet.createRow(0);// 建立新行

					for (int j = 0; j < excelInfo.Headers.length; j++) {
						sheet.setColumnWidth(j, 5500);
						row.createCell(j).setCellValue(excelInfo.Headers[j]);
					}

					for (int m = 0; m < 65535 && rowCurrent < rowAllCount; m++) {
						Object obj = data.get(m);
						row = sheet.createRow(m + 1);// 建立新行
						Class cl = obj.getClass();
						
						for (int p = 0; p < excelInfo.Propertys.length; p++) {
							String name = excelInfo.Propertys[p];
							
							Field field = cl.getDeclaredField(name);
							
							field.setAccessible(true);
							
							Object value = field.get(obj);
							
							String valuestr = (value == null ? "NULL" : value
									.toString());

							if (excelInfo.ContentFormat[p] == null
									|| "".equals(excelInfo.ContentFormat[p])) {
								row.createCell(p).setCellValue(
										valuestr.toString());
							} else if (excelInfo.ContentFormat[p]
									.indexOf("{image}") < 0) {
								row.createCell(p).setCellValue(
										excelInfo.ContentFormat[p].replace(
												"%v", valuestr));
							}
						}
						this.progress = ((float) rowCurrent + 1)
								/ ((float) rowAllCount);
						rowCurrent++;
					}
				}
			} else {
				int i = 0;
				
				System.out.println("======>" + excelInfo.SheetName
						.replace("%i", String.valueOf((k + 1 ) * (i + 1))));
				
				HSSFSheet sheet = workBook.createSheet(excelInfo.SheetName
						.replace("%i", String.valueOf((k + 1 ) * (i + 1))));
				
				HSSFRow row = sheet.createRow(0);// 建立新行
				for (int j = 0; j < excelInfo.Headers.length; j++) {					
					sheet.setColumnWidth(j, 5500);
					
					row.createCell(j).setCellValue(excelInfo.Headers[j]);
				}
				this.progress = 1;
			}
		}

		/*workBook.write(fileOut);
		fileOut.close();*/
		return  workBook;
	}

	/**************************************************************************
	 * 
	 * 函数名：main <br>
	 * <br>
	 * 功能：<br>
	 * <br>
	 * 作者： ChenKQ 2013-3-10<br>
	 * <br>
	 * 参数表：<br>
	 * 
	 * @param args
	 * <br>
	 * <br>
	 *            返回值：<br>
	 *            void <br>
	 *            修改记录：<br>
	 *            日期 修改人 修改说明<br>
	 * 
	 **************************************************************************/
	public static void main(String[] args) {
		try {
			ExcelMultiWriter excelMultiWriter = new ExcelMultiWriter("D:/test.xls");

			ExcelInfo excelInfo = new ExcelInfo();

			excelInfo.SheetName = "第%i页";

			excelInfo.Headers = new String[] { "姓名", "年龄", "薪资" };

			excelInfo.Propertys = new String[] { "name", "age", "salary" };

			excelInfo.ContentFormat = new String[] { null, null, "$%v" };

			List[] datas = new ArrayList[] { new ArrayList(), new ArrayList(),
					new ArrayList() };
			
			//Random rd = new Random();
			
			/*for(int i = 0;i<datas.length;i++)
			{
				for(int j = 0;j < 100;j++)
				{
					Staff staff = new Staff();
					
					staff.setAge(rd.nextInt(21) + 18);
					
					staff.setName("NULL");
					
					staff.setSalary(rd.nextInt(5000) + 2000);
					
					datas[i].add(staff);
				}
			}*/

			excelMultiWriter.write(datas, new ExcelInfo[]{excelInfo,excelInfo,excelInfo});
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	static class Staff
	{
		private String name;
		private int age;
		private float salary;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public float getSalary() {
			return salary;
		}
		public void setSalary(float salary) {
			this.salary = salary;
		}
		
		
	}

	/**
	 * 
	 * 获取输入流的字节数组
	 * 
	 * @param inputStream
	 *            输入流
	 * @return 字节数组
	 */
	private byte[] getInputStreamBytes(InputStream inputStream) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[2048];
		int len;
		byte[] result = null;
		try {
			while ((len = inputStream.read(buffer)) > -1) {
				baos.write(buffer, 0, len);
			}

			try {
				result = baos.toByteArray();
				baos.close();
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
}
